﻿#ifndef __AF_LINK_H__
#define __AF_LINK_H__


namespace AF
{
	//template<class T> class Struct -* _INTERFACE ForEach
		template<class T> class Link;
}
#define AF_CLink			AF::Link

#include "AF_Struct.h"
#include "AF_MemManage.h"

#define AF_LINK_THIS			(Link<T>*)this

namespace AF
{
	/// 链表结构模板类
	template<class T>
	class Link : public Struct<T>
	{
 	private:
		struct Node
		{
			T		tType;
			Node*		pnPrev;
			Node*		pnNext;
		};

	public:
		Link();
		virtual ~Link();

	public:
		/// 添加节点
		int			Add(const T& tNew);			// 追加节点（在链表之后）
		/// 插入节点
		int			Insert					// 插入节点（在pNode之前，pNode为空时插入在链表最后）
					(const T& tNew, const T* ptNode = NULL);
		/// 移除指定节点
		bool			Remove(const T& tNode);			// 移除指定节点
		/// 清除全部节点
		bool			Clean(T* _OUT ptReturn = NULL);	// 清除全部节点

		/// 查找节点
		int			Find(const T& tNode, Node** _OUT ppnNode = NULL);		// 查找
		/// 获得头节点内容
		T&			GetHead();				// 获得头指针
		/// 获得尾节点内容
		T&			GetEnd();				// 获得尾指针
		/// 获得指定序号节点内容
		T&			GetAt(UINT nID);			// 获得指定ID指针		

		Pointer			Foreach(bool isFirst);			// Foreach循环
		UINT			GetCount();				// 获得数量

		/// 设置节点最大数量
		void			SetSize(UINT nSize);			// 设置最大长度

	private:
// 		bool			Clean(AF_TYPE* AF_OUT ptReturn)		// 清除全部节点(不适用次结构)
// 					{return true;}
		
	protected:
		/// 头节点指针
		Node*			m_pnHead;
		/// 尾节点指针
		Node*			m_pnEnd;
		/// 遍历循环时的当前节点
		Node*			m_pnForEachCur;
		/// 链表结构长度
		UINT			m_nLength;
		/// 链表最大数量
		UINT			m_nSize;
		/// 空节点内容
		T			m_tNull;
	};


	template<class T>
	Link<T>::Link() :
		m_pnHead	(NULL),
		m_pnEnd		(NULL),
		m_pnForEachCur	(NULL),
		m_nLength	(0),
		m_nSize		(0)
	{
		_MEMSET(&m_tNull, 0, sizeof(T));
	}

	template<class T>
	Link<T>::~Link()
	{
		Clean();
	}

	template<class T>
	int Link<T>::Add(const T& tNew)
	{
		if(m_nSize > 0)
		{
			AF_CHECK_R(m_nLength < m_nSize, -1);
		}

		Node* pnNew = AF_NEW(Node);
		pnNew->pnPrev = NULL;
		pnNew->pnNext = NULL;
		_MEMCPY(&pnNew->tType, &tNew, sizeof(T));

		if(m_pnEnd == NULL)
		{
			m_pnHead = m_pnEnd = pnNew;
		}
		else
		{
			m_pnEnd->pnNext = pnNew;
			pnNew->pnPrev = m_pnEnd;
			m_pnEnd = pnNew;
		}
		m_nLength += 1;
		return m_nLength - 1;
	}

	template<class T>
	int Link<T>::Insert(const T& tNew, const T* ptNode)
	{
		if(m_nSize > 0)
		{
			AF_CHECK_R(m_nLength < m_nSize, -1);
		}

		if(ptNode == NULL)
			return Add(tNew);

		Node* pnCur = NULL;
		int nCurID = Find(*ptNode, /*(void**)*/&pnCur);
		if(nCurID >= 0)
		{
			Node* pnNew = AF_NEW(Node);
			pnNew->pnPrev = NULL;
			pnNew->pnNext = NULL;
			_MEMCPY(&pnNew->tType, &tNew, sizeof(T));

 			if(pnCur == m_pnHead)
 			{
 				m_pnHead->pnPrev = pnNew;
				pnNew->pnNext = m_pnHead;
 				m_pnHead = pnNew;
 			}
 			else
 			{
				Node* pPrev = pnCur->pnPrev;
	 
				pPrev->pnNext = pnNew;
				pnNew->pnNext = pnCur;

				pnCur->pnPrev = pnNew;
				pnNew->pnPrev = pPrev;
 			}
	 
 			m_nLength++;
		}

 		return nCurID;
	}

	template<class T>
	bool Link<T>::Remove(const T& tNode)
	{
		Node* pnCur = NULL;
		if(Find(tNode, /*(void**)*/&pnCur) < 0)
			return false;

		if(m_pnForEachCur == pnCur)
			m_pnForEachCur = pnCur->pnPrev;

		if(pnCur == m_pnHead)
		{
			m_pnHead = pnCur->pnNext;
		}
		else
		{
			pnCur->pnPrev->pnNext = pnCur->pnNext;
		}

		if(pnCur == m_pnEnd)
		{
			m_pnEnd = pnCur->pnPrev;
		}
		else
		{
			pnCur->pnNext->pnPrev = pnCur->pnPrev;
		}

		pnCur->pnPrev = NULL;
		pnCur->pnNext = NULL;

		AF_DELETE(pnCur);
		m_nLength--;

		return true;
	}

	template<class T>
	bool Link<T>::Clean(T* _OUT ptReturn)
	{
		int _nID = 0;

		Node* pnCur = NULL;
		while(m_pnHead != NULL)
		{
			pnCur = m_pnHead;
			pnCur->pnPrev = NULL;
			m_pnHead = pnCur->pnNext;
			pnCur->pnNext = NULL;

			if(ptReturn != NULL)
				_MEMCPY(&ptReturn[_nID], &(pnCur->tType), sizeof(T));

			_nID++;
			AF_DELETE(pnCur);
		}

		m_pnEnd = NULL;
		m_pnForEachCur = NULL;
		m_nLength = 0;

		return true;
	}

	template<class T>
	int Link<T>::Find(const T& tNode, Node** _OUT ppnNode)
	{
		Node* pnCur = m_pnHead;
		int nCurID = 0;

		while(pnCur != NULL)
		{
			if(_MEMCMP(&pnCur->tType, &tNode, sizeof(T)) == 0)
				break;
			pnCur = pnCur->pnNext;
			nCurID++;
		}

		if((UINT)nCurID >= m_nLength)
			nCurID = -1;
		else if(ppnNode != NULL)
			*ppnNode = /*(void*)*/pnCur;

		return nCurID;
	}

	template<class T>
	T& Link<T>::GetHead()
	{
		AF_CHECK_R(m_nLength > 0, m_tNull);

		return m_pnHead->tType;
	}

	template<class T>
	T& Link<T>::GetEnd()
	{
		AF_CHECK_R(m_nLength > 0, m_tNull);

		return m_pnEnd->tType;
	}

	template<class T>
	T& Link<T>::GetAt(UINT nID)
	{
		AF_CHECK_R(m_nLength > 0, m_tNull);
		AF_CHECK_R((int)nID >= 0 && (int)nID < m_nLength, m_tNull);

		Node* pnCur = m_pnHead;
		UINT nCurID = 0;

		while(pnCur != NULL)
		{
			if(nCurID == nID)
				break;
			pnCur = pnCur->pnNext;
			nCurID++;
		}

		return pnCur->tType;
	}

	template<class T>
	Pointer Link<T>::Foreach(bool isFirst)
	{
		if(isFirst)
		{
			m_pnForEachCur = m_pnHead;
		}
		else if(m_pnForEachCur == NULL)
		{
			m_pnForEachCur = m_pnHead;
		}
		else if(m_pnForEachCur != NULL)
		{
			m_pnForEachCur = m_pnForEachCur->pnNext;
		}

		if(m_pnForEachCur == NULL)
			return NULL;

		return (Pointer)(&m_pnForEachCur->tType);
	}

	template<class T>
	UINT Link<T>::GetCount()
	{
		return m_nLength;
	}

	template<class T>
	void Link<T>::SetSize(UINT nSize)
	{
		m_nSize = nSize;
	}
}

#endif